package cn.lyd.user.service.impl;

import cn.lyd.basic.constant.WxConstants;
import cn.lyd.basic.dto.LoginDto;
import cn.lyd.basic.exception.BusinessException;
import cn.lyd.basic.util.AjaxResult;
import cn.lyd.basic.util.HttpUtil;
import cn.lyd.basic.util.Md5Utils;
import cn.lyd.basic.util.StrUtils;
import cn.lyd.user.domain.Logininfo;
import cn.lyd.user.domain.User;
import cn.lyd.user.domain.Wxuser;
import cn.lyd.user.mapper.LogininfoMapper;
import cn.lyd.user.mapper.UserMapper;
import cn.lyd.user.mapper.WxuserMapper;
import cn.lyd.user.service.ILogininfoService;
import cn.lyd.basic.service.impl.BaseServiceImpl;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 业务实现类：
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements ILogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WxuserMapper wxuserMapper;

    @Autowired
    private  UserMapper userMapper;


    /**
     * 账号登录
     * @param loginDto
     * @return
     */
    @Override
    public Map<String, Object> accoutLogin(LoginDto loginDto) {
        String account = loginDto.getAccount();
        String checkPass = loginDto.getCheckPass();
        //一、校验-空值校验
        if (StringUtils.isEmpty(account) || StringUtils.isEmpty(checkPass)){
            throw new BusinessException("信息不能为空");
        }
        //二、校验-账号正确
        Logininfo logininfo = logininfoMapper.findByAccount(loginDto);
        if (logininfo==null) {
            throw new BusinessException("账号或密码不正确");
        }

        //三：校验 - 密码 - 加密加盐
        //前端输入的密码进行加密加盐
        String inputPwd = Md5Utils.encrypByMd5(checkPass + logininfo.getSalt());
        if (!inputPwd.equals(logininfo.getPassword())) {
            throw new BusinessException("账号或密码不正确");
        }
        //四、校验-账号是否被禁用  ---默认是启用的
        if (!logininfo.getDisable()){
            throw  new BusinessException("此账号已被禁用，请联系管理员");
        }

        //五、生成token，并将登录信息保存到redis数据库，设置30分钟有效
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);

        //六、封装返回值
        Map<String, Object> map = new HashMap<>();
        map.put("token",token);
        //为了安全，去除密码
        logininfo.setPassword(null);
        logininfo.setSalt(null);
        map.put("logininfo",logininfo);
        return map;
    }


    /**
     * 微信登录
     * @param code
     * @return
     */
    @Override
    public AjaxResult wechatLogin(String code) {
        //1.组装第二个请求地址---replace替换字符串
        String url = WxConstants.GET_ACK_URL.replace("APPID",WxConstants.APPID)
                .replace("SECRET",WxConstants.SECRET).replace("CODE",code);

        //二、使用HttpUtil工具类发送请求，返回json格式的字符串
        String jsonStr = HttpUtil.httpGet(url);

        //三、将json格式的字符串转换成json对象。并获取里面的token和openid
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String accessToken = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");

        //四：根据openid去查t_wxuser表
        Wxuser wxuser = wxuserMapper.loadByOpenid(openid);
        //如果通过openid查询到了wxuser对象，并且绑定了user对象
        if (wxuser!=null) {//绑定过
            User user = userMapper.findById(wxuser.getUserId());
            if (user!=null) {//并且绑定了user对象
                //免密登录
                //如果绑定了，user对象也存在，就查询logininfo对象
                Logininfo logininfo = logininfoMapper.findById(user.getLogininfoId());
                String token = UUID.randomUUID().toString();//生成随机的36位字符串
                //存到redis中
                redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);
                //将数据传给前端---将token和登录信息保存到map再到AjaxResult的resultObject中进行返回给前端
                Map<String, Object> map = new HashMap<>();
                map.put("token",token);
                //为了安全，去除密码
                logininfo.setPassword(null);
                logininfo.setSalt(null);
                map.put("logininfo",logininfo);
                //把map放到AjaxResult里的ResultObj里
                return AjaxResult.me().setResultObj(map);
            }
        }
        //没有走完if =两种情况
            //1.没绑定
            //2.绑定了但user对象被注销了
        String params = "?accessToken="+accessToken+"&openid="+openid;
        return AjaxResult.me().setSuccess(false).setResultObj(params);
    }

    /**
     * 微信绑定
     * @param map
     * @return
     */
    @Override
    public AjaxResult wechatBinder(Map<String, String> map) {
        String phone = map.get("phone");
        String verifyCode = map.get("verifyCode");
        String accessToken = map.get("accessToken");
        String openid = map.get("openid");
        //1.校验-空值校验-用户输入的手机号和验证码
            if (StringUtils.isEmpty(phone)||StringUtils.isEmpty(verifyCode)) {
                throw new BusinessException("信息不能为空");
            }
        //2.校验- 手机验证码校验：是否正确，是否过期【binder:18012321397 - 9527:1232141413】
            Object obj = redisTemplate.opsForValue().get("binder:" + phone);//9527:1232141413
            //验证手机验证码是否过期
            if (obj==null){
                throw new BusinessException("手机验证码过期");
            }
            //验证手机验证码是否正确  obj.toString().split(":")[0] ----  9527
            if (!obj.toString().split(":")[0].equals(verifyCode)) {
                throw new BusinessException("手机验证码错误");
            }

        //3.组装第三个请求
            String url = WxConstants.GET_USER_URL.replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openid);
        //4.通过token和openid发送第三个请求，返回json格式的字符串
            String jsonStr = HttpUtil.httpGet(url);

        //5.使用fastJson将json格式的字符串转成json对象，再转成一个Wxuser对象【没有user_id】
            Wxuser wxuser =jsonStr2Wxuser(jsonStr);
        //6.先通过openid去找t_wxuser,如果有直接删除
            Wxuser dbWxuser = wxuserMapper.loadByOpenid(openid);
            if (dbWxuser!=null) {
                wxuserMapper.del(dbWxuser.getId());
            }
        //7.想办法创建一个user对象-通过phone去创建一个User对象，密码是多少？-随机
            User user = userMapper.findByPhone(phone);//以前是通过手机号注册，现在又想通过微信绑定登录
            if (user==null) {//如果user不存在
                user=phone2User(phone);//就把手机号当成username
                Logininfo logininfo = user2Logininfo(user);

                logininfoMapper.add(logininfo);
                user.setLogininfoId(logininfo.getId());
                //8.添加User对象=>生成一个自增id，.=>将User_id设置到WxUser对象
                userMapper.add(user);
            }
        //9.添加WxUser到数据库
            wxuser.setUserId(user.getId());
            wxuserMapper.add(wxuser);
        //10.免密登录
            //如果绑定了，user对象也存在，就查询logininfo对象
                Logininfo logininfo = logininfoMapper.findById(user.getLogininfoId());
                String token = UUID.randomUUID().toString();//生成随机的36位字符串
            //存到redis中
                redisTemplate.opsForValue().set(token,logininfo,30, TimeUnit.MINUTES);
            //将数据传给前端---将token和登录信息保存到map再到AjaxResult的resultObject中进行返回给前端
                Map<String, Object> resulMap = new HashMap<>();
                resulMap.put("token",token);
            //为了安全，去除密码
                logininfo.setPassword(null);
                logininfo.setSalt(null);
                resulMap.put("logininfo",logininfo);
            //把map放到AjaxResult里的ResultObj里
                return AjaxResult.me().setResultObj(resulMap);
    }

    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);//类型：用户
        logininfo.setDisable(true);//启用状态
        return logininfo;
    }


    private User phone2User(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        String salt = StrUtils.getComplexRandomString(32);
        String pwd = StrUtils.getRandomString(6);//随机6位密码
        String md5Pwd = Md5Utils.encrypByMd5(pwd + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        user.setState(1);
        return user;
    }

    private Wxuser jsonStr2Wxuser(String jsonStr) {
         JSONObject jsonObj = JSONObject.parseObject(jsonStr);
                 /*
                     "openid":"OPENID",
                     "nickname":"NICKNAME",
                     "sex":1,
                     "province":"PROVINCE",
                     "city":"CITY",
                     "country":"COUNTRY",
                     "headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
                     "privilege":[
                     "PRIVILEGE1",
                     "PRIVILEGE2"
                     ],
                     "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
                     * */
         Wxuser wxuser = new Wxuser();
         wxuser.setOpenid(jsonObj.getString("openid"));
         wxuser.setNickname(jsonObj.getString("nickname"));
         wxuser.setHeadimgurl(jsonObj.getString("headimgurl"));
         wxuser.setUnionid(jsonObj.getString("unionid"));
         return wxuser;


    }
}
